<script setup>

import {onBeforeUnmount, onMounted, ref} from "vue";
import {EventAction, Meta2d, deepClone} from "@meta2d/core";
import {data as dataComponents} from "@/views/topology/data/Components";
import bus from "@/views/topology/lib/bus";
import {register, registerHighcharts} from "@meta2d/chart-diagram";
import {flowPens} from "@meta2d/flow-diagram";
import {activityDiagram, activityDiagramByCtx} from "@meta2d/activity-diagram";
import {sequencePens, sequencePensbyCtx} from "@meta2d/sequence-diagram";
import {classPens} from "@meta2d/class-diagram";
import {useMeta2dStore} from "@/views/topology/utils/meta2dStore";

const store = useMeta2dStore()
const options = ref({});
const meta2d = ref({store: {active: [{devName:{}}]}});
const componentsData = ref({});
const active = ref([]);
const topicMap = ref({})

onMounted(() => {
    bus.$on("exitEditor", () => {
        exitEditor();
    });
    bus.$on("onDragStart", (e) => {
        onDragStart(e);
    })
    bus.$on("onTouchStart", (e) => {
        onTouchStart(e)
    })
    //锁定视图
    bus.$on("onLocker", () => {
        // 不触发任何操作和事件
            meta2d.value.lock(10);
    });
    //锁定视图
    bus.$on("onLocker2", () => {
        //禁止编辑+移动
            meta2d.value.lock(2);
    });
    //解锁视图
    bus.$on("unLocker", () => {
        //未锁定
        meta2d.value.lock(0);
    });
    //设置视图大小
    bus.$on("scale", (v) => {
        meta2d.value.scale(v);
        meta2d.value.centerView();
    });
    //设置视图大小
    bus.$on("fitView", () => {
        meta2d.value.fitView();
        bus.$emit("fitViewComplete", meta2d.value.store.data.scale);
    });
    //撤销
    bus.$on("undo", () => {
        meta2d.value.undo();
    });
    //重做
    bus.$on("redo", () => {
        meta2d.value.redo();
    });
    //剪切
    bus.$on("cut", () => {
        meta2d.value.cut();
    });
    //复制
    bus.$on("copy", () => {
        meta2d.value.copy();
    });
    //粘贴
    bus.$on("paste", () => {
        meta2d.value.paste();
    });
    //更改连线类型
    bus.$on("updateLineType", (e) => {
        for (const data of meta2d.value.store.active) {
            meta2d.value.updateLineType(data, e);
        }
    });
    //更改画笔属性
    bus.$on("setPen", (obj) => {
        console.log(obj, "==setPenobj==");
        meta2d.value.setValue(obj);
    });
    //播放动画
    bus.$on("startAnimate", (penid) => {
        meta2d.value.startAnimate(penid);
    });
    //暂停动画
    bus.$on("pauseAnimate", (penid) => {
        meta2d.value.pauseAnimate(penid);
    });
    //结束动画
    bus.$on("stopAnimate", (penid) => {
        meta2d.value.stopAnimate(penid);
    });
    //保存
    bus.$on("saveTopology", () => {
        console.log("保存");
        save();
    });
    //下载
    bus.$on("download", () => {
        // console.log("下载");
        download();
    });
    bus.$on("open",(e)=>{
        // console.log("打开")
        onOpen(e);
    })
    //打开json
    bus.$on("openJson", (json) => {
        console.log(json, "===json===");
        meta2d.value.clear();
        meta2d.value.open(json);
        mqttInt()
        meta2d.value.lock(0);
        meta2d.value.inactive();
    });
    //链接mqtt
    bus.$on("connectMqtt", (params) => {
        mqttInt(params)
    });
    //放大镜
    bus.$on("toggleMagnifier", () => {
        meta2d.value.toggleMagnifier();
    });
    //鹰眼
    bus.$on("showMap", (prams) => {
        if (prams) {
            meta2d.value.showMap();
        } else {
            meta2d.value.hideMap();
        }

    });
    //开始钢笔
    bus.$on("drawLine", () => {
        meta2d.value.drawLine('curve');
    });
    //开始铅笔
    bus.$on("drawingPencil", () => {
        meta2d.value.drawingPencil();
    });

    bus.$on("saveCSV",()=>{
        exportCSV()
    })


    meta2d.value = new Meta2d("meta2d", options.value)
    // store.dispatch("setMeta2d",meta2d.value)
    meta2d.value.setBackgroundColor('#f4f4f5')
    active.value = meta2d.value.store.active
    for (const info of dataComponents)
        componentsData.value[info.name] = info;
    meta2d.value.beforeAddPens = beforeAddPens;

    registerHighcharts();
    register();
    meta2d.value.register(flowPens())
    meta2d.value.register(activityDiagram())
    // 原生canvas绘画的图库，支持逻辑复杂的需求
    meta2d.value.registerCanvasDraw(activityDiagramByCtx())
    meta2d.value.register(sequencePens())
    meta2d.value.registerCanvasDraw(sequencePensbyCtx())
    meta2d.value.register(classPens())
    meta2d.value.on('active', activeFn);
    meta2d.value.on('inactive',inactiveFn);
    //mqtt推送回调数据处理
    meta2d.value.socketFn = (message, topic) => {
        meta2d.value.setValue({id: topicMap.value[topic], text: JSON.parse(message).msg})
    }
    document.querySelectorAll("canvas")[1].style.left = "0";
    meta2d.value.inactive();

})
onBeforeUnmount(() => {
    bus.$off("onDragStart");
    bus.$off("onTouchStart");
    bus.$off("exitEditor");
    bus.$off("onLocker");
    bus.$off("onLocker2");
    bus.$off("unLocker");
    bus.$off("scale");
    bus.$off("fitView");
    bus.$off("undo");
    bus.$off("redo");
    bus.$off("cut");
    bus.$off("copy");
    bus.$off("paste");
    bus.$off("updateLineType");
    bus.$off("setPen");
    bus.$off("startAnimate");
    bus.$off("pauseAnimate");
    bus.$off("stopAnimate");
    bus.$off("saveTopology");
    bus.$off("download");
    bus.$off("openJson");
    bus.$off("connectMqtt");
    bus.$off("open");
    meta2d.value.off('active',activeFn);
    meta2d.value.off('inactive',inactiveFn);
})

//方法
const beforeAddPens = async (pens) => {
    // console.log("addPens",pens);
    // 1. window.confirm 会阻塞后面代码，不推荐
    // return window.confirm("是否添加此类图元？");

    // 2. Promise 类型 Modal
    // showDialog 伪代码，需自行实现
    // 返回 true 允许 remove
    return true;
}
const onDragStart = (obj) => {
    // console.log("拖拽")
    // console.log(meta2d.value.store.active)
    exitEditor();
    const {e, item} = obj;
    const setObj = {
        ...componentsData.value[item.data.name],
        type: 0,
        ...item.data,
        ...(item.data.rect ? item.data.rect : {}),
        ...(item.data.data ? item.data.data : {}),
        events: [
            {
                name: "click",
                action: EventAction.Link, // 执行动作
                where: {key: "text", comparison: "==", value: "圆角矩形"}, // 触发条件
                value: "2ds.le5le.com",
            },
        ],
    };
    e.dataTransfer.setData("Text", JSON.stringify(setObj));
}
const onTouchStart = (obj) => {
    // console.log("点击")
    exitEditor();
    const {item} = obj;
    const setObj = {
        ...componentsData.value[item.data.name],
        type: 0,
        ...item.data,
        ...(item.data.rect ? item.data.rect : {}),
        ...(item.data.data ? item.data.data : {}),
    };
    if (item.name === "涂鸦" || item.name === "涂鸦2") {
        meta2d.value.drawingPencil();
        return;
    }
    if (item.name === "钢笔") {
        meta2d.value.drawLine("line");
        return;
    }
    if (item.name === "钢笔节点") {
        meta2d.value.drawLine("curve");
        return;
    }
    if (item.name === "钢笔闭合节点") {
        meta2d.value.drawLine("polyline");
        return;
    }
    meta2d.value.canvas.addCaches = deepClone([setObj]);
}

const exitEditor = () => {
    meta2d.value.inactive();
    meta2d.value.stopPencil();
    meta2d.value.finishDrawLine();
}

const saveAsCSV = (header,data)=>{
    let csv = '';
    for (const key in header)
        csv +=`${key},`;
    csv = `${csv.slice(0,Math.max(0, csv.length-1))}\r\n`;
    for (const i in data){
        for (const key in header)
            csv+=`${data[i][key]},`
        csv = `${csv.slice(0,Math.max(0, csv.length-1))}\r\n`;
    }
    //定义文件内容，类型必须为Blob 否则createObjectURL会报错
    const content = new Blob([`\uFEFF${csv}`]);
    //生成url对象
    const urlObject = window.URL || window.webkitURL || window;
    const url = urlObject.createObjectURL(content);
    //生成<a></a>DOM元素
    const el = document.createElement("a");
    //链接赋值
    el.href = url;
    let name = `${Date.parse(new Date())}.csv`
    el.download = name.toString();
    //必须点击否则不会下载
    el.click();
    //移除链接释放资源
    urlObject.revokeObjectURL(url);
}

const exportCSV = ()=>{
    let obj;
    obj = {...deepClone(meta2d.value.store.data)};
    const header = {"id":"id","begin":"begin","end":"end"};
    const relations = obj.pens.filter(pen=>pen.type===1);
    const data = relations.map(relation=>{return Object.assign({},{'id':relation.id,
        'begin':relation.anchors[0].connectTo,'end':relation.anchors[1].connectTo})})
    saveAsCSV(header,data)
}
const save = () => {
    let obj;
    obj = {...deepClone(meta2d.value.store.data)};
    const assets = obj.pens.filter(pen=>pen.type===0);
    const data = assets.map(asset=>{return Object.assign({},{'id':asset.id,'name':asset.devName.name,
    'ip':asset.devName.ip})})
    saveJSON(
        data,
        obj.name?`${obj.name}.json`:`${Date.parse(new Date())}.json`
    );
}
const base64toFile = (data, fileName) => {
    const dataArr = data.split(",");
    const byteString = atob(dataArr[1]);
    const options = {
        type: "image/jpeg",
        endings: "native"
    };
    const u8Arr = new Uint8Array(byteString.length);
    for (let i = 0; i < byteString.length; i++) {
        u8Arr[i] = byteString.charCodeAt(i);
    }
    return new File([u8Arr], `${fileName  }.jpg`, options);//返回文件流
}
const onOpen = (e) => {
    //官方存储
    const file = e.target.files[0];
    if (!file) {
        return;
    }
    const reader = new FileReader();
    reader.onload = (event) => {
        try {
            const json = JSON.parse(event.target.result);
            window.meta2d.open(json);
        } catch {
            // eslint-disable-next-line no-console
            console.log("读取文件失败，请检查数据格式");
        }
    };
    reader.readAsText(file);
}
const onSave = () => {
    //官方保存
    const filename = "测试数据.json";
    const data = window.meta2d.data();
    const json = JSON.stringify(data, undefined, 4);
    const blob = new Blob([json], {type: "text/json"});
    const a = document.createElement("a");
    a.download = filename;
    a.href = window.URL.createObjectURL(blob);
    a.dataset.downloadurl = ["text/json", a.download, a.href].join(":");
    a.click();
}
const download = () => {
    let obj;
    const {color, activeColor, grid, gridColor, gridSize, rule, ruleColor} =
        meta2d.value.getOptions();
    obj = {
        color,
        activeColor,
        grid,
        gridColor,
        gridSize,
        rule,
        ruleColor,
        ...deepClone(meta2d.value.store.data),
    };
    saveJSON(
        obj,
        obj.name ? `${obj.name  }.json` : `${Date.parse(new Date())  }.json`
    );
}
const saveJSON = (data, filename) => {
    if (!data) {
        alert("保存的数据为空");
        return;
    }
    if (!filename) filename = "json.json";
    if (typeof data === "object") {
        data = JSON.stringify(data);
    }
    const blob = new Blob([data], {type: "text/json"});
    // console.log(blob, "==blob==");
    // a标签实现兼容IE下载
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveOrOpenBlob(blob, filename);
    } else {
        // for Non-IE (chrome, firefox etc.)
        // console.log(blob)
        // 兼容不同浏览器的URL对象
        const downloadUrl = window.URL || window.webkitURL || window.moxURL;
        // console.log(downloadUrl);
        // console.log(blob);
        // 创建下载链接
        const downloadHref = downloadUrl.createObjectURL(blob);
        // 创建a标签并为其添加属性
        const downloadLink = document.createElement("a");
        downloadLink.href = downloadHref;
        downloadLink.download = filename;
        // 触发点击事件执行下载
        downloadLink.click();
    }
    console.log("下载完成了，嘿嘿")
}
const mqttInt = (params) => {
    if (!params) {
        console.log('===mqttInt==')
        for (const key in meta2d.value.store.pens) {
            if (getTopic(meta2d.value.store.pens[key])) {
                topicMap.value[getTopic(meta2d.value.store.pens[key])] = key
            }
        }
    } else {
        meta2d.value.closeMqtt()
        let string = ''
        for (const key in meta2d.value.store.pens) {
            if (getTopic(meta2d.value.store.pens[key])) {
                string = `${string  },${  getTopic(meta2d.value.store.pens[key])}`
                topicMap.value[getTopic(meta2d.value.store.pens[key])] = key
            }
        }
        string = string.slice(1)
        params.mqttTopics = string
        console.log(params, '==params==')
        meta2d.value.connectMqtt(params);
    }
}
const activeFn = (data) => {
    if (data.length!==0) {
        if (data[0].devName === undefined) {
            data[0].devName = {
                name: "",
                ip: "",
            }
        }
        store.active = data;
        store.meta2d = meta2d.value;
    }
}

const inactiveFn = (data) =>{
    store.active = [];
    store.meta2d = meta2d.value
}

</script>

<template>
    <div id="meta2d"/>
</template>

<style scoped>
#meta2d {
    width: 100%;
    height: 840px;
    position: relative;
}
</style>